package com.chinamobile.iot.rest;

import com.alibaba.fastjson.JSON;
import com.chinamobile.iot.handler.model.SubMessageData;
import com.chinamobile.iot.handler.sub.NettyMqttClient;
import com.chinamobile.iot.mqtt.spi.model.StoredMessage;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.client.OkHttp3ClientHttpRequestFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;

import java.util.HashMap;
import java.util.Map;

import static com.chinamobile.iot.handler.sub.SendSubConst.CLIENT_ID_SEND_SUB;
import static com.chinamobile.iot.handler.sub.SendSubConst.TOPIC_SEND_SUB;

/**
 * Created by szl on 2017/6/9.
 */
@Component
public class BrokerClient {


    private static Logger logger = LoggerFactory.getLogger(BrokerClient.class);

    // 查询设备是否在线的URL GET
    private final static String URL_IS_ONLINE = "http://{host}:{port}/devices/online?mqttId={mqttId}";
    // 向设备下发命令的URL POST
    private final static String URL_SEND_COMMAND = "http://{host}:{port}/devices/{mqttId}/cmd?commandId={commandId}&type={type}";
    // 向本broker发送批量订阅消息 POST
    private final static String URL_SEND_SUB_MESSAGES = "http://{host}:{port}/subscriptions?filter={filter}";
    // 向本broker发送单条订阅消息，POST
    private final static String URL_SEND_SUB_MESSAGE = "http://{host}:{port}/subscription?filter={filter}";
    // 向broker发送单条订阅消息，GET，通过GET方式发送，GET时，调用性能会比POST时快
    private final static String URL_SEND_SUB_MESSAGE_BY_GET = "http://{host}:{port}/subscription?filter={filter}&message={message}";

    // 强迫设备下线的URL
    private final static String URL_OFFLINE_DEVICE = "http://{host}:{port}/devices/offline/{mqttId}";

    private RestTemplate restTemplate;

    @Autowired(required = false)
    private NettyMqttClient nettyMqttClient;

    public void init() {
        restTemplate = new RestTemplate();
        OkHttp3ClientHttpRequestFactory okHttpClientHttpRequestFactory = new OkHttp3ClientHttpRequestFactory();
        okHttpClientHttpRequestFactory.setConnectTimeout(3000);
        okHttpClientHttpRequestFactory.setReadTimeout(3000);
        okHttpClientHttpRequestFactory.setWriteTimeout(3000);
        restTemplate.setRequestFactory(okHttpClientHttpRequestFactory);
    }

    public void close() {
    }

    public boolean isOnline(String host, int port, String deviceId) {
        Map<String, Object> params = new HashMap<String, Object>(3);
        params.put("host", host);
        params.put("port", port);
        params.put("mqttId", deviceId);
        return restTemplate.getForObject(URL_IS_ONLINE, Boolean.class, params);
    }

    public boolean sendCommand(String host, int port, String deviceId, String commandId, String type, String content) {
        Map<String, Object> params = new HashMap<String, Object>(5);
        params.put("host", host);
        params.put("port", port);
        params.put("mqttId", deviceId);
        params.put("commandId", commandId);
        params.put("type", type);
        return restTemplate.postForObject(URL_SEND_COMMAND, content, Boolean.class, params);
    }

    public void sendSubMessages(String host, int port, String filter, StoredMessage[] messages) {
        Map<String, Object> params = new HashMap<String, Object>(3);
        params.put("host", host);
        params.put("port", port);
        params.put("filter", filter);
        restTemplate.postForObject(URL_SEND_SUB_MESSAGES, messages, Void.class, params);
    }

    public boolean sendSubMessage(String host, int port, String filter, StoredMessage message) {
        boolean result = false;
        try {
            if (nettyMqttClient != null) {
                if (!nettyMqttClient.isConnected(host, port)) {
                    nettyMqttClient.connect(host, port, CLIENT_ID_SEND_SUB, null, null, true, 120);
                    Thread.sleep(10);
                    if (nettyMqttClient.isConnected(host, port)){
                        SubMessageData data = new SubMessageData(message, filter);
                        String payload = JSON.toJSONString(data);
                        result = nettyMqttClient.publish(host, port, TOPIC_SEND_SUB, payload, 1);
                    }
                }
                else{
                    SubMessageData data = new SubMessageData(message, filter);
                    String payload = JSON.toJSONString(data);
                    result = nettyMqttClient.publish(host, port, TOPIC_SEND_SUB, payload, 1);
                }


            }
        }
        catch (Exception e){
            logger.warn("send message to {}:{} failed", host, port);
            result = false;
        }

        return result;
    }


    public boolean offlineDevice(String host, int port, String deviceId) {
        Map<String, Object> params = new HashMap<String, Object>(3);
        params.put("host", host);
        params.put("port", port);
        params.put("mqttId", deviceId);
        return restTemplate.postForObject(URL_OFFLINE_DEVICE, null, Boolean.class, params);
    }
}
